package com.sayice.robotconflict.game.handler;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.sayice.robotconflict.common.exception.AppException;
import com.sayice.robotconflict.common.exception.ErrorCode;
import com.sayice.robotconflict.common.util.SpringContextUtil;
import com.sayice.robotconflict.entity.PlayerEntity;
import com.sayice.robotconflict.entity.RobotEntity;
import com.sayice.robotconflict.game.msg.Message;
import com.sayice.robotconflict.game.msg.data.receive.RobotUpdateInfo;
import com.sayice.robotconflict.game.msg.data.send.PlayerInfo;
import com.sayice.robotconflict.game.object.Player;
import com.sayice.robotconflict.service.BagService;
import com.sayice.robotconflict.service.PlayerService;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 玩家信息消息处理器
 *
 * @author shubing
 */
@Slf4j
public class PlayerHandler extends ChannelInboundHandlerAdapter {
    private static final PlayerService PLAYER_SERVICE = SpringContextUtil.getBean(PlayerService.class);
    
    private static final BagService BAG_SERVICE = SpringContextUtil.getBean(BagService.class);
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        Object[] playerAndMsg = (Object[]) msg;
        Player player = (Player) playerAndMsg[0];
        Message message = (Message) playerAndMsg[1];
        if ("player".equals(message.getType())) {
            if (player.state.get() != Player.State.IDLE) {
                return;
            }
            switch (message.getAction()) {
                case "ranking": {
                    ctx.channel().writeAndFlush(new Message("player", "ranking", getRanking()).toJson());
                    break;
                }
                case "info": {
                    ctx.channel().writeAndFlush(new Message("player", "info", getPlayerInfo(player.id)).toJson());
                    break;
                }
                case "addRobot": {
                    try {
                        RobotUpdateInfo robotUpdateInfo = ((JSONObject) message.getData()).to(RobotUpdateInfo.class);
                        BAG_SERVICE.addRobot(player.id, robotUpdateInfo.getRobot());
                    } catch (JSONException e) {
                        throw new AppException(ErrorCode.CODE_400, "机器人逻辑格式不正确");
                    }
                    // 更新在线玩家携带的机器人
                    player.setCarriedRobots(BAG_SERVICE.queryCarriedRobots(player.id));
                    // 发送新数据给客户端
                    ctx.channel().writeAndFlush(new Message("player", "info", getPlayerInfo(player.id)).toJson());
                    break;
                }
                case "updateRobot": {
                    try {
                        RobotUpdateInfo robotUpdateInfo = ((JSONObject) message.getData()).to(RobotUpdateInfo.class);
                        BAG_SERVICE.updateRobotByIndex(player.id, robotUpdateInfo.getIndex(), robotUpdateInfo.getRobot());
                    } catch (JSONException e) {
                        throw new AppException(ErrorCode.CODE_400, "机器人逻辑格式不正确");
                    }
                    // 更新在线玩家携带的机器人
                    player.setCarriedRobots(BAG_SERVICE.queryCarriedRobots(player.id));
                    // 发送新数据给客户端
                    ctx.channel().writeAndFlush(new Message("player", "info", getPlayerInfo(player.id)).toJson());
                    break;
                }
                case "deleteRobot": {
                    BAG_SERVICE.deleteRobotByIndex(player.id, (int) message.getData());
                    // 更新在线玩家携带的机器人
                    player.setCarriedRobots(BAG_SERVICE.queryCarriedRobots(player.id));
                    // 发送新数据给客户端
                    ctx.channel().writeAndFlush(new Message("player", "info", getPlayerInfo(player.id)).toJson());
                    break;
                }
                default:
                    break;
            }
        } else {
            ctx.fireChannelRead(playerAndMsg);
        }
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("NettyHandler Exception from " + ctx.channel().remoteAddress(), cause);
        ctx.channel().close();
    }
    
    /**
     * 获取排行榜
     */
    private List<PlayerInfo> getRanking() {
        List<PlayerEntity> playerEntities = PLAYER_SERVICE.queryRanking();
        return BeanUtil.copyToList(playerEntities, PlayerInfo.class);
    }
    
    /**
     * 获取玩家信息
     *
     * @param id 玩家ID
     */
    private PlayerInfo getPlayerInfo(String id) {
        PlayerEntity playerEntity = PLAYER_SERVICE.queryById(id);
        List<RobotEntity> robotEntities = BAG_SERVICE.queryRobots(id);
        PlayerInfo playerInfo = BeanUtil.copyProperties(playerEntity, PlayerInfo.class);
        playerInfo.setRobots(robotEntities);
        return playerInfo;
    }
}
